package com.leehom.arch.storage.handler;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.leehom.arch.storage.exception.FileStorageException;
import com.leehom.arch.storage.exception.MessageCode;
import com.leehom.arch.storage.model.FileItem;
import com.leehom.arch.storage.model.Storage;

import io.minio.BucketExistsArgs;
import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.ListObjectsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveBucketArgs;
import io.minio.RemoveObjectArgs;
import io.minio.Result;
import io.minio.http.Method;
import io.minio.messages.Item;
import lombok.Setter;
/**
 * 
 * @类名: MinIOFileStorageHandler
 * @说明: minio存储实现
 *
 * @author   leehom
 * @Date	 2018年3月13日 下午2:38:42
 * 修改记录：
 *
 * @see
 */
public class MinIOFileStorageHandler extends BaseFileStorageHandler implements FileStorageHandler {
	
	private static Logger logger = LoggerFactory.getLogger(MinIOFileStorageHandler.class);
	
	@Setter
    private MinioClient minioClient;
    
    @Override
	public String schema() {
		return "minio";
	}

	@Override
	public InputStream getFile(String path, String fileName, Storage storage) throws FileStorageException {
		try {
			return minioClient.getObject(GetObjectArgs.builder().bucket(path).object(fileName).build());
		} catch (Exception e) {
			throw new FileStorageException(MessageCode.ERROR_STORAGE_MINIOGETFILE, path, fileName, e.getMessage());
		}
	}

	@Override
	public List<FileItem> listFileOfDir(String path, Storage storage) throws FileStorageException {
        Iterable<Result<Item>> results = minioClient.listObjects(
            	ListObjectsArgs.builder().bucket(path).build()
            );
        List<FileItem> items = Lists.newArrayList();
        for(Result<Item> r : results) {
        	FileItem fi = minioItem2FileItem(path, r);
        	items.add(fi);
        }
		return items;
	}

	private FileItem minioItem2FileItem(String path, Result<Item> r) throws FileStorageException {
		try {
			Item i = r.get();
			FileItem item = new FileItem();
			item.setName(i.objectName());
			item.setPath(path);
			item.setSize(i.size());
			item.setDir(i.isDir());
			if(!i.isDir())
				item.setLastUpdateTime(i.lastModified().toInstant().toEpochMilli());
			return item;
		} catch (Exception e) {
			throw new FileStorageException(MessageCode.ERROR_STORAGE_MINIOLISTFILE, path, e.getMessage()); 
		} 

	}
	
	@Override
	public void saveFile(String path, String fileName, InputStream inStream, Storage storage) throws FileStorageException {
        try {
			minioClient.putObject(
			        PutObjectArgs.builder().bucket(path).object(fileName)
			                .stream(inStream, inStream.available(), -1).build());
		} catch (Exception e) {
			throw new FileStorageException(MessageCode.ERROR_STORAGE_MINIOSAVEFILE, path, fileName, e.getMessage()); 
		} 
	}

	@Override
	public String getUrl(String path, String fileName, Storage storage) {
        try {
            String url = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(path)
                            .object(fileName)
                            // .expiry(validTime, timeUnit) // 过期
                            .build());
            return url;
        } catch (Exception e) {
        	throw new FileStorageException(MessageCode.ERROR_STORAGE_MINIOGETURL, path, fileName, e.getMessage()); 
        }
	}

	@Override
	public void deleteFile(String path, String fileName, Storage storage) {
		try {
			minioClient.removeObject(RemoveObjectArgs.builder().bucket(path).object(fileName).build());
		} catch (Exception e) {

		} 
		
	}

	@Override
	public void deleteDir(String path, Storage storage) {
        try {
			minioClient.removeBucket(RemoveBucketArgs.builder()
			        .bucket(path)
			        .build());
		} catch (Exception e) {
			throw new FileStorageException(MessageCode.ERROR_STORAGE_MINIOGETFILE, path, "", e.getMessage()); 
		}
		
	}

	/**
     * 查看存储bucket是否存在
     *
     * @param bucketName 存储bucket
     * @return boolean
	 * @throws IOException 
     */
    public Boolean bucketExists(String bucketName) throws Exception {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());

    }
  
    /**
     * 创建存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     * @throws Exception 
     */
    public void makeBucket(String bucketName) throws Exception {
        minioClient.makeBucket(MakeBucketArgs.builder()
                .bucket(bucketName)
                .build());
    }
 
}
